package com.authine.cloudpivot.web.api.controller.common;

import com.aliyun.oss.OSS;
import com.aliyun.oss.model.OSSObject;
import com.authine.cloudpivot.engine.api.model.runtime.AttachmentModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectModel;
import com.authine.cloudpivot.engine.enums.type.FileUploadType;
import com.authine.cloudpivot.web.api.exception.PortalException;
import com.authine.cloudpivot.web.api.exception.ResultEnum;
import com.authine.cloudpivot.web.api.handler.CustomizedOrigin;
import com.authine.cloudpivot.web.api.oss.FileStorageConfiguration;
import com.authine.cloudpivot.web.api.oss.OSSClient;
import com.authine.cloudpivot.web.api.service.impl.FescoadQueryServiceImpl;
import com.authine.cloudpivot.web.api.sftp.SFTPClient;
import com.authine.cloudpivot.web.api.view.system.OssConfigVO;
import com.google.common.base.Charsets;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Map;

/**
 * @description:
 * @author: zyj
 * @time: 2022/5/16 9:19
 */

@Api(tags = "公共服务::自定义文件上传下载")
@RestController
@RequestMapping("/api/aliyun")
@Slf4j
@CustomizedOrigin(level = 1)
@Primary
public class CustomizedOSSController extends OSSController {

    private static final String MIMETYPE_SUFFIX = "application/";
    private static final String IMAGE_SUFFIX = "image/";
    private static final String PIC_EXTENSION = ".jpg.JPG.png.PNG.jpeg.JPEG";

    @Autowired
    private OSSClient ossClient;
    @Autowired
    private SFTPClient sftpClient;
    @Autowired
    private RedisTemplate<String, AttachmentModel> redisTemplate;
    @Autowired
    private FescoadQueryServiceImpl fescoadQueryService;

    @Override
    @GetMapping(value = "/download")
    @ResponseBody
    @ApiOperation(value = "oss 文件下载接口")
    @ApiImplicitParam(
            name = "refId",
            value = "资源id",
            required = true,
            dataType = "String",
            paramType = "query")
    public void download(@RequestParam String refId, HttpServletResponse response) {
        super.validateNotEmpty(refId, "refId 不能为空");
        if (refId.contains(".") && FileStorageConfiguration.getFileUploadType() == FileUploadType.FTP) {
            response.setCharacterEncoding(Charsets.UTF_8.name());
            String suffix = refId.substring(refId.lastIndexOf('.') + 1);
            if (PIC_EXTENSION.contains(suffix)) {
                //IE图片展示兼容性
                if (".jpg.JPG".contains(suffix)) {
                    suffix = "jpeg";
                }
                response.setContentType(IMAGE_SUFFIX.concat(suffix));
            } else {
                response.setContentType(MIMETYPE_SUFFIX.concat(refId.substring(refId.lastIndexOf('.') + 1)));
            }
            try {
                //判断是否是IE11
                String header = getRequest().getHeader("User-Agent").toUpperCase();
                Boolean flag = header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE");
                if (flag) {
                    response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(refId, "UTF-8"));
                } else {
                    response.setHeader("Content-Disposition", "attachment; filename=" + new String(refId.getBytes("utf-8"), "ISO8859-1"));
                }
                sftpClient.downloadFile(refId, response);
            } catch (Exception e) {
                log.warn(e.getMessage(), e);
            }
            return;
        }
        AttachmentModel resourceModel = getBizObjectFacade().getAttachmentByRefId(refId);
        if (resourceModel == null) {
            Object object = redisTemplate.boundHashOps(KEY_WORKFLOW_ATTACHMENT).get(refId);
            resourceModel = (AttachmentModel) object;
        }
        if (resourceModel == null) {
            throw new PortalException(
                    ResultEnum.OSS_DOWNLOAD_PERMISSION_ERR.getErrCode(),
                    ResultEnum.OSS_DOWNLOAD_PERMISSION_ERR.getErrMsg());
        }
        //获取下载信息
        Map<String,Object> map = fescoadQueryService.getAttMessage(refId);

        BizObjectModel objectModel = new BizObjectModel();
        objectModel.setSchemaCode("downLog");
        objectModel.setSequenceStatus("COMPLETED");
        Map<String, Object> data = objectModel.getData();
        data.put("sheetName",map.get("sheetName"));
        data.put("attName",map.get("name"));
        getBizObjectFacade().saveBizObject(getUserId(),objectModel,false);

        if (FileStorageConfiguration.getFileUploadType() == FileUploadType.OSS) {
            log.debug("the download type is sso");
            OSS client = null;
            try {

                String ossKey = resourceModel.getRefId();
                OssConfigVO ossConfig = ossClient.getOssConfig();
                client = ossClient.getClient(ossConfig);
                OSSObject ossObject = client.getObject(ossConfig.getBucket(), ossKey);
                if (ossObject == null) {
                    throw new PortalException(ResultEnum.OSS_UPLOAD_ERR.getErrCode(), "OSS 文件不存在：refId=".concat(ossKey));
                }
                InputStream inputStream = ossObject.getObjectContent();
                response.setCharacterEncoding(Charsets.UTF_8.name());
                response.setContentType(resourceModel.getMimeType());
                response.setHeader(
                        "Content-Disposition",
                        "attachment; fileName=" + URLEncoder.encode(resourceModel.getName(), "UTF-8"));
                //response.getOutputStream().write(IOUtils.toByteArray(inputStream));
                IOUtils.copy(inputStream, response.getOutputStream());
            } catch (IOException e) {
                log.warn("文件下载失败: {}", e.getMessage(), e);
                throw new PortalException(ResultEnum.OSS_UPLOAD_ERR.getErrCode(), ResultEnum.OSS_UPLOAD_ERR.getErrMsg());
            } finally {
                if (client != null) {
                    client.shutdown();
                }
            }
        } else {
            log.debug("the download type is sftp");
            String fileName = resourceModel.getRefId().concat(resourceModel.getName());
            response.setCharacterEncoding(Charsets.UTF_8.name());
            response.setContentType(resourceModel.getMimeType());
            try {
                String header = getRequest().getHeader("User-Agent").toUpperCase();
                Boolean flag = header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE");
                if (flag) {
                    response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(resourceModel.getName(), "UTF-8"));
                } else {
                    response.setHeader("Content-Disposition", "attachment; filename=" + new String(resourceModel.getName().getBytes("utf-8"), "ISO8859-1"));
                }
                sftpClient.downloadFile(fileName, response);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }
}
